//
//  Date+SGExtension.swift
//  QingLiuSwift
//
//  Created by xyanl on 2024/11/1.
//  Copyright © 2024 考拉🐨. All rights reserved.
//

import Foundation
import Localize_Swift

extension Date: SpadgerCompatible {}

/// 时间戳的类型
public enum SGTimestampType: Int {
    /// 秒 10位
    case second
    /// 毫秒 13位
    case millisecond
    /// 微秒 16位
    case microsecond
}

public enum SGWeekType: Int {
    /// 秒 10位
    case second
    /// 毫秒 13位
    case millisecond
    /// 微秒 16位
    case microsecond
}

// MARK: - 一、Date 基本的扩展
public extension Spadger where Base == Date {
    /// 从 Date 获取年份
    var year: Int {
        Calendar.current.component(Calendar.Component.year, from: self.base)
    }
    
    /// 从 Date 获取月份
    var month: Int {
        Calendar.current.component(Calendar.Component.month, from: self.base)
    }
    
    /// 从 Date 获取 日
    var day: Int {
        Calendar.current.component(.day, from: self.base)
    }
    
    /// 从 Date 获取 小时
    var hour: Int {
        Calendar.current.component(.hour, from: self.base)
    }
    
    /// 从 Date 获取 分钟
    var minute: Int {
        Calendar.current.component(.minute, from: self.base)
    }
    
    /// 从 Date 获取 秒
    var second: Int {
        Calendar.current.component(.second, from: self.base)
    }
    
    /// 从 Date 获取 毫秒
    var nanosecond: Int {
        Calendar.current.component(.nanosecond, from: self.base)
    }
    
    // 从日期获取 星期名称(中文)
    var weekNameChinese: String {
        let weekdays = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
        var calendar = Calendar(identifier: .gregorian)
        let timeZone = TimeZone(identifier: "Asia/Shanghai")
        calendar.timeZone = timeZone!
        let theComponents = calendar.dateComponents([.weekday], from: self.base as Date)
        return  weekdays[theComponents.weekday! - 1]
    }
    
    /// 从日期获取 星期名称，跟随系统语言的变化而变换结果的语言
    /// - Returns: EEEE：中文返星期四，英文返 Thursday
    ///            EE：中文返周四，英文返 Thu
    func weekName(_ dateFormat: String = "EEEE") -> String {
        sg_formatter.dateFormat = dateFormat
        return sg_formatter.string(from: self.base)
    }
    
    
    /// 时间延续
    /// 以 date 为时间起点，type 是延续的单位，scale 范围，
    /// 🌰：date = Date(), type = .day，scale：2，以当前时间为起点，获取未来 2 天后的时间
    /// - Parameters:
    ///   - date: 时间起点
    ///   - type: 时间单位类型，年、月、日、时、分、秒、周
    ///   - scale: 范围， >0:未来的时间， <0:过去的时间
    /// - Returns: date
    static func timeContinuation(from date: Date, type: Calendar.Component, scale: Int) -> Date {
        var components = DateComponents()
        switch type {
        case .year:
            components.year = scale
            
        case .month:
            components.month = scale
            
        case .day:
            components.day = scale
            
        case .hour:
            components.hour = scale
            
        case .minute:
            components.minute = scale
            
        case .second:
            components.second = scale
            
        case .weekday:
            components.weekday = scale
            
        default:
            break
        }
        
        return Calendar.current.date(byAdding: components, to: date)!
    }
    
    
    
    /// date 转 ISO8601
    /// - Parameter date: date description
    /// - Returns: ISO8601 字符串 例：2024-02-23T10:10:13.928+08:00
    static func ISO8601(from date: Date) -> String {
        // iOS-NSISO8601DateFormatter
        // https://www.jianshu.com/p/f6b5adb2e470
        
        let dateFormatter: ISO8601DateFormatter = ISO8601DateFormatter()
        dateFormatter.formatOptions = [.withYear, .withMonth, .withDay, .withDay, .withFullTime, .withDashSeparatorInDate]
        // 将系统时区设置为当前时区，如果不设置默认是0时区
        dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
        
        return dateFormatter.string(from: date)
    }
    
    
    /// RFC1123格式的日期由英文标识星期几、日期、月份、年份、时区和时间组成
    /// - Parameter date: 需要转换的日期
    /// - Returns: RFC1123 格式的字符串
    static func RFC1123(from date: Date = Date()) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US")
        dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
        dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
        return dateFormatter.string(from: date)
    }
    
}


/// 时间格式转换
public extension Spadger where Base == Date {
    
    /// Date 转 时间戳
    /// Date().sg.timestamp(.second)
    /// - Parameter type: 返回的时间戳类型，默认是秒
    /// - Returns: 时间戳
    func timestamp(_ type: SGTimestampType = .second) -> Int {
        Date.sg.timestamp(from: base, type)
    }
    
    /// Date 转 时间戳, 默认当前时间戳
    /// Date.sg.timestamp(from: base, type)
    /// - Parameters:
    ///   - date: date
    ///   - type: 时间戳类型
    /// - Returns: 时间戳
    static func timestamp(from date: Date = Date(), _ type: SGTimestampType = .second) -> Int {
        let timestamp: TimeInterval = date.timeIntervalSince1970
        if type == .second {
            // 10位数时间戳
            return Int(timestamp)
            
        } else if type == .millisecond {
            // 毫秒 13位
            return Int(timestamp * 1000)
            
        }
        // 微秒 16位
        return Int(timestamp * 1000 * 1000)
    }
    
    
    /// 带格式的时间 转 时间戳，支持返回 13位 和 10位的时间戳，时间字符串和时间格式必须保持一致
    /// - Parameters:
    ///   - timeString: 时间字符串，如：2024-11-01 17:36:59
    ///   - formatter: 时间格式，如：yyyy-MM-dd HH:mm:ss
    ///   - timestampType: 返回的时间戳类型，默认：秒
    /// - Returns: 返回 时间戳
    static func timestamp(from time: String, formatter: String, type: SGTimestampType = .second) -> Int {
        sg_formatter.dateFormat = formatter
        sg_formatter.locale = NSLocale.system
        guard let date = sg_formatter.date(from: time) else {
#if DEBUG
            fatalError("日期格式不匹配")
#else
            return 0
#endif
        }
        if type == .second {
            return Int(date.timeIntervalSince1970)
        }
        return Int((date.timeIntervalSince1970) * 1000)
    }
    
    
    /// 时间戳 转 date
    /// - Parameters:
    ///   - timestamp: 时间戳
    /// - Returns: 返回 Date
    static func date(from timestamp: Int) -> Date {
        guard String(timestamp).count == 10 ||  String(timestamp).count == 13 else {
#if DEBUG
            fatalError("时间戳位数不是 10 也不是 13 timestamp: \(timestamp)")
#else
            return Date()
#endif
        }
        let timestampValue = String(timestamp).count == 10 ? timestamp : timestamp / 1000
        // 时间戳转为Date
        return Date(timeIntervalSince1970: TimeInterval(timestampValue))
    }
    
    /// 带格式的时间字符串 转 Date
    /// - Parameters:
    ///   - time: 时间字符串
    ///   - formatter: 时间格式
    /// - Returns: 返回 Date
    static func date(time: String, formatter: String) -> Date {
        sg_formatter.dateFormat = formatter
        sg_formatter.locale = NSLocale.system
        guard let date = sg_formatter.date(from: time) else {
#if DEBUG
            fatalError("时间有问题")
#else
            return Date()
#endif
        }
        /*
         guard let resultDate = getNowDateFromatAnDate(date) else {
         return Date()
         }
         */
        return date
    }
    
    
    /// 时间戳 转化为 对应时间格式的字符串
    /// - Parameters:
    ///   - timestamp: 时间戳(支持10位和13位)
    ///   - format: 格式
    /// - Returns: 对应时间的字符串
    static func timeString(from timestamp: Int, formatter: String = "yyyy-MM-dd HH:mm:ss") -> String {
        // 时间戳转为Date
        let date = date(from: timestamp)
        // 设置 dateFormat
        sg_formatter.dateFormat = formatter
        // 按照dateFormat把Date转化为String
        return sg_formatter.string(from: date)
    }
    
    /// Date 转 对应格式的时间字符串
    /// - Parameter formatter: 时间格式
    /// - Returns: 返回 timeString
    static func timeString(from date: Date = Date(), formatter: String = "yyyy-MM-dd HH:mm:ss") -> String {
        sg_formatter.timeZone = TimeZone.autoupdatingCurrent
        sg_formatter.dateFormat = formatter
        return sg_formatter.string(from: date)
    }
    
    
    /// Date 转 DateComponents
    /// - Parameter date: date description
    /// - Returns: DateComponents
    static func dateComponents(from date: Date = Date()) -> DateComponents {
        
        let unit: Set<Calendar.Component> = [
            .era, .year, .month, .day, .hour, .minute, .second,
            .weekday, .weekdayOrdinal, .weekOfMonth, .weekOfYear,
            .nanosecond, .calendar, .timeZone, .yearForWeekOfYear, .quarter
        ]
        // 创建一个NSCalendar对象
        let calendar = Calendar.current
        let components = calendar.dateComponents(unit, from: date)
        
        return components
    }
    
    
    /// 比较两个日期
    /// - Parameters:
    ///   - components: 时间组件 例：[.day, .hour]
    ///   - fromDate: fromDate description
    ///   - toDate: toDate description
    /// - Returns: 相差 1 天 5 小时
    static func compare(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents {
        Calendar.current.dateComponents(components, from: start, to: end)
    }
    
    
    static func getDateDisplay(timeStamp: Int) -> String {
        
        if timeStamp <= 0{
            return "刚刚".localized()
        }
        
        let inputDate = Date.sg.date(from: timeStamp)
        let nowDate = Date()
        
        guard inputDate.sg.isThisYear else {
            // 不是今年的, 显示 年月日
            return Date.sg.timeString(from: inputDate, formatter: "yyyy-MM-dd")
        }
        
        guard Calendar.current.isDate(inputDate, equalTo: nowDate, toGranularity: .month) else {
            // 不是本月的, 显示 月日
            return Date.sg.timeString(from: inputDate, formatter: "MM-dd")
        }
        
        guard inputDate.sg.isToday else {
            // 不是今天的
            // 相差的天数
            let number = Date.sg.compare([.day], from: inputDate, to: nowDate).day!
            
            if number > 9 {
                return Date.sg.timeString(from: inputDate, formatter: "MM-dd")
            }
            
            if number == 0 {
                return "昨天".localized()
            }
            
            if number == 2 {
                // return "前天".localized()
            }
            
            return "\(number)" + "天前".localized()
        }
        
        /// 相差的小时数
        var hourNumber = Date.sg.compare([.hour], from: nowDate, to: inputDate).hour!
        hourNumber = labs(hourNumber)
        if hourNumber > 0 {
            return "\(hourNumber)" + "小时前".localized()
        }
        
        var minutesNumber = Date.sg.compare([.minute], from: nowDate, to: inputDate).minute!
        minutesNumber = labs(minutesNumber)
        if minutesNumber > 0 {
            return "\(minutesNumber)" + "分钟前".localized()
        }
        
        return "刚刚".localized()
    }
    
    
    /// 消息的时间显示
    /// - Parameter timeStamp: 时间戳
    /// - Returns: 显示内容
    static func messageDateDisplay(_ timeStamp: Int) -> String {
        
        let date = Date.sg.date(from: timeStamp)
        
        // 今天
        if date.sg.isToday {
            return Date.sg.timeString(from: timeStamp, formatter: "HH:mm")
        }
        
        // 昨天
        if date.sg.isYesterday {
            return Date.sg.timeString(from: timeStamp, formatter: "昨天 HH:mm")
        }
        
        // 显示昨天之前的一周
        let number = Date.sg.compare([.day], from: date, to: Date()).day!
        let range = 1...8
        if range.contains(number) {
            let weekStr = date.sg.weekNameChinese
            return weekStr + Date.sg.timeString(from: timeStamp, formatter: "HH:mm")
        }
        
        // 今年的
        if date.sg.isThisYear {
            return Date.sg.timeString(from: timeStamp, formatter: "MM月dd日 HH:mm")
        }
        
        // 往年的时间日期
        return Date.sg.timeString(from: timeStamp, formatter: "yyyy年MM月dd日 HH:mm")
    }
    
}

public extension Spadger where Base == Date {
    
    /// 今天的日期
    static var todayDate: Date {
        Date()
    }
    
    /// 昨天的日期
    static var yesterDayDate: Date {
        Calendar.current.date(byAdding: DateComponents(day: -1), to: Date())!
    }
    
    /// 明天的日期
    static var tomorrowDate: Date {
        Calendar.current.date(byAdding: DateComponents(day: 1), to: Date())!
    }
    
    /// 是否为今天（只比较日期，不比较时分秒）
    /// - Returns: bool
    var isToday: Bool {
        Calendar.current.isDate(self.base, inSameDayAs: Date())
    }
    
    /// 是否为昨天
    var isYesterday: Bool {
        // 比较当前的日期和昨天的日期
        Calendar.current.isDate(self.base, inSameDayAs: Base.sg.yesterDayDate)
    }
    
    /// 是否为今年
    var isThisYear: Bool  {
        let calendar = Calendar.current
        let nowCmps = calendar.dateComponents([.year], from: Date())
        let selfCmps = calendar.dateComponents([.year], from: self.base)
        return nowCmps.year == selfCmps.year
    }
    
    /// 是否为  同一年  同一月 同一天
    /// - Returns: bool
    func isSameDay(date: Date) -> Bool {
        Calendar.current.isDate(self.base, inSameDayAs: date)
    }
    
    /// 当前日期是不是润年
    var isLeapYear: Bool {
        let year = base.sg.year
        return ((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0)))
    }
    
    /// 是否为12小时制
    /// - Returns: true：12小时，否则24小时
    static var isTwelve: Bool {
        var isTwelve: Bool = false
        if let formatString = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current), formatString.contains("a") {
            // 12 小时制
            isTwelve = true
        } else {
            // 24 小时制
            isTwelve = false
        }
        return isTwelve
    }
    
    /// 获取当前日期中某月的天数
    /// - Parameter month: 某月，1：一月
    /// - Returns: 天数，0：表示无效的月份
    func monthOfDays(month: Int) -> Int {
        switch month {
        case 1, 3, 5, 7, 8, 10, 12:
            return 31
        case 4, 6, 9, 11:
            return 30
        case 2:
            return self.base.sg.isLeapYear ? 29: 28
        default:
            return 0
        }
    }
}
